0.1 Survival Analysis in R

https://rviews.rstudio.com/2017/09/25/survival-analysis-with-r/


Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

0.1.1 Censored Data

 [1]  72  411  228  126  118   10   82  110  314  100+  42    8  144   25+  11   30  384    4   54   13  123+  97+ 153   59  117   16  151   22   56   21   18 
[32] 139   20   31   52  287   18   51  122   27   54    7   63  392   10    8   92   35  117  132   12  162    3   95  177  162  216  553  278   12  260  200 
[63] 156  182+ 143  105  103  250  100  999  112   87+ 231+ 242  991  111    1  587  389   33 

0.1.2 Kaplan Meier

Call: survfit(formula = Surv(time, status) ~ 1, data = veteran)

      n  events  median 0.95LCL 0.95UCL 
    137     128      80      52     105 

0.1.3 Life Table

Call: survfit(formula = Surv(time, status) ~ 1, data = veteran)

 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    1    137       2    0.985  0.0102      0.96552       1.0000
   30     97      39    0.700  0.0392      0.62774       0.7816
   60     73      22    0.538  0.0427      0.46070       0.6288
   90     62      10    0.464  0.0428      0.38731       0.5560
  180     27      30    0.222  0.0369      0.16066       0.3079
  270     16       9    0.144  0.0319      0.09338       0.2223
  360     10       6    0.090  0.0265      0.05061       0.1602
  450      5       5    0.045  0.0194      0.01931       0.1049
  540      4       1    0.036  0.0175      0.01389       0.0934
  630      2       2    0.018  0.0126      0.00459       0.0707
  720      2       0    0.018  0.0126      0.00459       0.0707
  810      2       0    0.018  0.0126      0.00459       0.0707
  900      2       0    0.018  0.0126      0.00459       0.0707

0.1.5 KM per treatment group

Call: survfit(formula = Surv(time, status) ~ trt, data = veteran)

       n events median 0.95LCL 0.95UCL
trt=1 69     64  103.0      59     132
trt=2 68     64   52.5      44      95

0.1.6 KM Graph per treatment group

2 OpenIntro Statistics

https://www.openintro.org/stat/surv.php

https://www.openintro.org/download.php?file=survival_analysis_in_R&referrer=/stat/surv.php

https://www.openintro.org/download.php?file=survival_analysis_in_R_code&referrer=/stat/surv.php

https://www.openintro.org/download.php?file=survival_analysis_in_R_code_df-cp&referrer=/stat/surv.php

Warning in install.packages :
  package ‘OIsurv’ is not available (for R version 3.5.1)
Error in library(OIsurv) : there is no package called ‘OIsurv’
 [1]   1    3    3    4   10   13   13   16   16   24   26   27 
[13]  28   30   30   32   41   51   65   67   70   72   73   77 
[25]  91   93   96  100  104  157  167   61+  74+  79+  80+  81+
[37]  87+  87+  88+  89+  93+  97+ 101+ 104+ 108+ 109+ 120+ 131+
[49] 150+ 231+ 240+ 400+
 [1] (51,52]  (58,59]  (55,57]  (28,50]  (21,51+] (19,47] 
 [7] (25,57]  (48,59]  (47,61]  (25,61+] (31,62+] (24,57+]
[13] (25,58+] (30,67+] (33,68+] (36,61]  (30,61+] (41,63] 
[19] (43,69]  (45,69]  (35,70+] (29,63+] (35,65+] (32,67] 
[25] (36,76]  (32,71+]
rm(list=ls())

#===> loading packages and such <===#
#install.packages("OIsurv")
library(OIsurv)
data(aids)
aids
attach(aids)
infect
detach(aids)
aids$infect

#===> survival object <===#
data(tongue); attach(tongue)   # the following will not affect computations
# create a subset for just the first group by using [type==1]
my.surv.object <- Surv(time[type==1], delta[type==1])
my.surv.object
detach(tongue)

data(psych); attach(psych)
my.surv.object <- Surv(age, age+time, death)
my.surv.object
detach(psych)

#===> K-M Estimate <===#
data(tongue); attach(tongue)
my.surv <- Surv(time[type==1], delta[type==1])
survfit(my.surv ~ 1)
my.fit <- survfit(my.surv ~ 1)
summary(my.fit)$surv     # returns the Kaplan-Meier estimate at each t_i
summary(my.fit)$time     # {t_i}
summary(my.fit)$n.risk   # {Y_i}
summary(my.fit)$n.event  # {d_i}
summary(my.fit)$std.err  # standard error of the K-M estimate at {t_i}
summary(my.fit)$lower    # lower pointwise estimates (alternatively, $upper)
str(my.fit)              # full summary of the my.fit object
str(summary(my.fit))     # full summary of the my.fit object
pdf("../figures/kmPlot.pdf", 7, 4.5)
plot(my.fit, main="Kaplan-Meier estimate with 95% confidence bounds",
   xlab="time", ylab="survival function")
dev.off()
my.fit1 <- survfit( Surv(time, delta) ~ type )   # here the key is "type"
detach(tongue)

#===> confidence bands <===#
data(bmt); attach(bmt)
my.surv <- Surv(t2[group==1], d3[group==1])
my.cb <- confBands(my.surv, confLevel=0.95, type="hall")
pdf("../figures/confBand.pdf", 8, 5)
plot(survfit(my.surv ~ 1), xlim=c(100, 600), xlab="time",
  ylab="Estimated Survival Function",
  main="Reproducing Confidence Bands for Example 4.2 in Klein/Moeschberger")

lines(my.cb$time, my.cb$lower, lty=3, type="s")
lines(my.cb$time, my.cb$upper, lty=3, type="s")
legend(100, 0.3, legend=c("K-M survival estimate",
  "pointwise intervals","confidence bands"), lty=1:3)
dev.off()
detach(bmt)


#===> cumulative hazard <===#
data(tongue); attach(tongue)
my.surv <- Surv(time[type==1], delta[type==1])
my.fit  <- summary(survfit(my.surv ~ 1))
H.hat   <- -log(my.fit$surv)
H.hat   <- c(H.hat, tail(H.hat, 1))
h.sort.of <- my.fit$n.event / my.fit$n.risk
H.tilde   <- cumsum(h.sort.of)
H.tilde   <- c(H.tilde, tail(H.tilde, 1))
pdf("../figures/cumHazard.pdf", 6, 4)
plot(c(my.fit$time, 250), H.hat, xlab="time", ylab="cumulative hazard",
  main="comparing cumulative hazards", ylim=range(c(H.hat, H.tilde)), type="s")
points(c(my.fit$time, 250), H.tilde, lty=2, type="s")
legend("topleft", legend=c("H.hat","H.tilde"), lty=1:2)
dev.off()
detach(tongue)


#===> mean/median <===#
data(drug6mp); attach(drug6mp)
my.surv <- Surv(t1, rep(1, 21))   # all placebo patients observed
survfit(my.surv ~ 1)
print(survfit(my.surv ~ 1), print.rmean=TRUE)
detach(drug6mp)

#===> test for 2+ samples <===#
data(btrial); attach(btrial)
survdiff(Surv(time, death) ~ im)   # output omitted
survdiff(Surv(time, death) ~ im, rho=1)   # output omitted
detach(btrial)

#===> coxph, time-independent <===#
data(burn); attach(burn)
my.surv   <- Surv(T1, D1)
coxph.fit <- coxph(my.surv ~ Z1 + as.factor(Z11), method="breslow")
coxph.fit
co <- coxph.fit$coefficients  # may use coxph.fit$coeff instead
va <- coxph.fit$var           # I^(-1), estimated cov matrix of the estimates
ll <- coxph.fit$loglik        # log-likelihood for alt and null MLEs, resp.
my.survfit.object <- survfit(coxph.fit)
hold <- survfit(my.surv ~ 1)
#source("http://www.stat.ucla.edu/~david/teac/surv/local-coxph-test.R")
coxph.fit
C   <- matrix(c(0, 1, 0, 0,
                0, 0, 1, 0,
                0, 0, 0, 1), nrow=3, byrow=TRUE)
d   <- rep(0, 3)
t1  <- C %*% co - d
t2  <- C %*% va %*% t(C)
XW2 <- c(t(t1) %*% solve(t2) %*% t1)
pchisq(XW2, 3, lower.tail=FALSE)
#local.coxph.test(coxph.fit, 2:4)
my.survfit.object <- survfit(coxph.fit)
detach(burn)


#===> coxph, time-dependent <===#
data(relapse)
relapse

N  <- dim(relapse)[1]
t1 <- rep(0, N+sum(!is.na(relapse$int)))  # initialize start time at 0
t2 <- rep(-1, length(t1))                 # build vector for end times
d  <- rep(-1, length(t1))                 # whether event was censored
g  <- rep(-1, length(t1))                 # gender covariate
i  <- rep(FALSE, length(t1))              # initialize intervention at FALSE

j  <- 1
for(ii in 1:dim(relapse)[1]){
  if(is.na(relapse$int[ii])){      # no intervention, copy survival record
    t2[j] <- relapse$event[ii]
    d[j]  <- relapse$delta[ii]
    g[j]  <- relapse$gender[ii]
    j <- j+1
  } else {                         # intervention, split records
    g[j+0:1] <- relapse$gender[ii] # gender is same for each time
    d[j]     <- 0                  # no relapse observed pre-intervention
    d[j+1]   <- relapse$delta[ii]  # relapse occur post-intervention?
    i[j+1]   <- TRUE               # intervention covariate, post-intervention
    t2[j]    <- relapse$int[ii]-1  # end of pre-intervention
    t1[j+1]  <- relapse$int[ii]-1  # start of post-intervention
    t2[j+1]  <- relapse$event[ii]  # end of post-intervention
    j <- j+2                       # two records added
  }
}

mySurv <- Surv(t1, t2, d)        # pg 3 discusses left-trunc. right-cens. data
myCPH  <- coxph(mySurv ~ g + i)

#data(burn); attach(burn)
##source("http://www.stat.ucla.edu/~david/teac/surv/time-dep-coxph.R")
#td.coxph <- timeDepCoxph(burn, "T1", "D1", 2:4, "Z1", verbose=FALSE)
#td.coxph   # some model output is omitted for brevity
#detach(burn)

#===> AFT models <===#
data(larynx)
attach(larynx)
srFit <- survreg(Surv(time, delta) ~ as.factor(stage) + age, dist="weibull")
summary(srFit)
srFitExp <- survreg(Surv(time, delta) ~ as.factor(stage) + age, dist="exponential")
summary(srFitExp)
srFitExp$coeff    # covariate coefficients
srFitExp$icoef    # intercept and scale coefficients
srFitExp$var      # variance-covariance matrix
srFitExp$loglik   # log-likelihood
srFit$scale       # not using srFitExp (defaulted to 1)
detach(larynx)

# Posted with permission of the code author:
# Beau Benjamin Bruce
# Author email: bbbruce@emory.edu
# 
# This code is available under GPL-2
# For license information, see
# http://cran.r-project.org/web/licenses/GPL-2

library(KMsurv)
data(burn)

#=====> Convert a data frame to a counting process version <=====#
#=====> Allows for time dependent variables to be introduced <=====#
df.cp = function(data,t.var,status.var,covars=setdiff(names(data),c(t.var,status.var))) {
  # data: data frame that represents the dataset
  # t.var: the column name of "data" that represents the survival time variable
  # status.var: the column name of "data" that represents the status variable
  # covars: list other covariates to retain
  
  # Returned object: a data frame that breaks each event down to a counting process
  
  # sorted times, append to 0
  t.sort <- c(0,sort(unlist(unique(data[t.var]))))
  
  # for each data point find times less than or equal to the obs' time
  t.list <- lapply(unlist(data[t.var]),function(x) t.sort[t.sort<=x])
  
  # create a list of datasets with covariates and all relevant start/stop times
  # use with to set the environment to the correct list item
  df.list <- lapply(seq_along(t.list),function(i) cbind(with(list(x=t.list[[i]]),
                     # start by removing one from end of x, stop by removing first of x
                     # include the status variable in the dataframe - helpful later                                        
                     data.frame(start=head(x,-1),stop=tail(x,-1),data[i,c(status.var,covars)]))))

  # do.call uses df.list as the argument for rbind
  df <- do.call(rbind,df.list)

  # create the correct status need last time for each
  # subject with status=1 to to be status=1 but all others status=0
  #
  # the lapply creates vectors 0,0,0,...,1 based on length of t.list
  # need to substract 2 because the lag takes one away, then need one for the 1 at end
  # do.call with c binds them together into a single vector
  # this is then multiplied by status to correct it
  keep.status <- do.call(c,lapply(t.list,function(x) c(rep(0,length(x)-2),1)))
  df[status.var] <- df[status.var] * keep.status
  df
}


#=====> Create the counting process data frame <=====#
burn.cp <- df.cp(burn,'T1','D1')
burn.cp <- within(burn.cp,{ T1Z1 <- log(stop)*Z1; }) 

#=====> Apply the Cox Proportional Hazards model <=====#
coxph(Surv(start,stop,D1) ~ Z1+Z2+Z3+T1Z1,data=burn.cp)

3 survsup

  • Plotting survival curves with the survsup package

https://cran.r-project.org/web/packages/survsup/vignettes/survsup_intro.html

http://github.com/dlindholm/survsup/

https://cran.r-project.org/package=gridExtra

LS0tCnRpdGxlOiAiTXkgUiBDb2RlcyBGb3IgRGF0YSBBbmFseXNpcyIKc3VidGl0bGU6ICJTdXJ2aXZhbCBBbmFseXNpcyIKYXV0aG9yOiAiW1NlcmRhciBCYWxjxLEsIE1ELCBQYXRob2xvZ2lzdF0oaHR0cHM6Ly93d3cuc2VyZGFyYmFsY2kuY29tLykiCmRhdGU6ICdgciBmb3JtYXQoU3lzLkRhdGUoKSlgJwpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgZmlnX2NhcHRpb246IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBwYXBlcgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNQogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgZGZfcHJpbnQ6IGthYmxlCiAgICBrZWVwX21kOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogY2VydWxlYW4KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgaGlnaGxpZ2h0OiBrYXRlCi0tLQoKIyMgU3Vydml2YWwgQW5hbHlzaXMgaW4gUgoKCmh0dHBzOi8vcnZpZXdzLnJzdHVkaW8uY29tLzIwMTcvMDkvMjUvc3Vydml2YWwtYW5hbHlzaXMtd2l0aC1yLwoKCmBgYHtyfQpsaWJyYXJ5KHN1cnZpdmFsKQpsaWJyYXJ5KHJhbmdlcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdnZm9ydGlmeSkKYGBgCgoKYGBge3J9CmRhdGEodmV0ZXJhbikKaGVhZCh2ZXRlcmFuKQpgYGAKCiMjIyBDZW5zb3JlZCBEYXRhCgpgYGB7cn0Ka20gPC0gd2l0aCh2ZXRlcmFuLCBTdXJ2KHRpbWUsIHN0YXR1cykpCgpoZWFkKGttLDgwKQoKYGBgCgoKIyMjIEthcGxhbiBNZWllciAKCmBgYHtyfQprbV9maXQgPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gdmV0ZXJhbikKCmttX2ZpdApgYGAKCgojIyMgTGlmZSBUYWJsZQoKYGBge3J9CnN1bW1hcnkoa21fZml0LCB0aW1lcyA9IGMoMSwzMCw2MCw5MCooMToxMCkpKQoKYGBgCgojIyMgS00gR3JhcGggT3ZlcmFsbAoKYGBge3J9CnBsb3Qoa21fZml0LCB4bGFiPSJEYXlzIiwgbWFpbiA9ICdLYXBsYW4gTWV5ZXIgUGxvdCcpICNiYXNlIGdyYXBoaWNzIGlzIGFsd2F5cyByZWFkeQoKYGBgCgoKYGBge3J9CmF1dG9wbG90KGttX2ZpdCkKCmBgYAoKCiMjIyBLTSBwZXIgdHJlYXRtZW50IGdyb3VwCgoKYGBge3J9CmttX3RydF9maXQgPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiB0cnQsIGRhdGEgPSB2ZXRlcmFuKQprbV90cnRfZml0CgpgYGAKCgojIyMgS00gR3JhcGggcGVyIHRyZWF0bWVudCBncm91cAoKCmBgYHtyfQphdXRvcGxvdChrbV90cnRfZml0KQpgYGAKCgoKCiMgc3Vydm1pbmVyCgpodHRwOi8vd3d3LnN0aGRhLmNvbS9lbmdsaXNoL3Jwa2dzL3N1cnZtaW5lci8jdWJlci1wbGF0aW51bS1jdXN0b21pemVkLXN1cnZpdmFsLWN1cnZlcwoKCgoKCjwhLS0gdmV0IDwtIG11dGF0ZSh2ZXRlcmFuLCBBRyA9IGlmZWxzZSgoYWdlIDwgNjApLCAiTFQ2MCIsICJPVjYwIiksIC0tPgo8IS0tICAgICAgICAgICAgICAgQUcgPSBmYWN0b3IoQUcpLCAtLT4KPCEtLSAgICAgICAgICAgICAgIHRydCA9IGZhY3Rvcih0cnQsbGFiZWxzPWMoInN0YW5kYXJkIiwidGVzdCIpKSwgLS0+CjwhLS0gICAgICAgICAgICAgICBwcmlvciA9IGZhY3RvcihwcmlvcixsYWJlbHM9YygiTjAiLCJZZXMiKSkpIC0tPgoKPCEtLSBrbV9BR19maXQgPC0gc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBBRywgZGF0YSA9IHZldCkgLS0+CjwhLS0ga21fQUdfZml0IC0tPgoKPCEtLSBhdXRvcGxvdChrbV9BR19maXQpIC0tPgoKCjwhLS0gRml0IENveCBNb2RlbCAtLT4KPCEtLSBjb3ggPC0gY294cGgoU3Vydih0aW1lLCBzdGF0dXMpIH4gdHJ0ICsgY2VsbHR5cGUgKyBrYXJubyArIGRpYWd0aW1lICsgYWdlICsgcHJpb3IgLCBkYXRhID0gdmV0KSAtLT4KPCEtLSBjb3ggLS0+CjwhLS0gc3VtbWFyeShjb3gpIC0tPgoKPCEtLSBjb3hfZml0IDwtIHN1cnZmaXQoY294KSAtLT4KPCEtLSBjb3hfZml0IC0tPgo8IS0tIHBsb3QoY294X2ZpdCwgbWFpbiA9ICJjcGggbW9kZWwiLCB4bGFiPSJEYXlzIikgLS0+CjwhLS0gYXV0b3Bsb3QoY294X2ZpdCkgLS0+Cgo8IS0tIGFhX2ZpdCA8LWFhcmVnKFN1cnYodGltZSwgc3RhdHVzKSB+IHRydCArIGNlbGx0eXBlICsgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgIGthcm5vICsgZGlhZ3RpbWUgKyBhZ2UgKyBwcmlvciAsICAtLT4KPCEtLSAgICAgICAgICAgICAgICBkYXRhID0gdmV0KSAtLT4KPCEtLSBhYV9maXQgLS0+CgoKPCEtLSAjc3VtbWFyeShhYV9maXQpICAjIHByb3ZpZGVzIGEgbW9yZSBjb21wbGV0ZSBzdW1tYXJ5IG9mIHJlc3VsdHMgLS0+CjwhLS0gYXV0b3Bsb3QoYWFfZml0KSAtLT4KCgo8IS0tICMgcmFuZ2VyIG1vZGVsIC0tPgo8IS0tIHJfZml0IDwtIHJhbmdlcihTdXJ2KHRpbWUsIHN0YXR1cykgfiB0cnQgKyBjZWxsdHlwZSArICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgIGthcm5vICsgZGlhZ3RpbWUgKyBhZ2UgKyBwcmlvciwgLS0+CjwhLS0gICAgICAgICAgICAgICAgIGRhdGEgPSB2ZXQsIC0tPgo8IS0tICAgICAgICAgICAgICAgICBtdHJ5ID0gNCwgLS0+CjwhLS0gICAgICAgICAgICAgICAgIGltcG9ydGFuY2UgPSAicGVybXV0YXRpb24iLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgc3BsaXRydWxlID0gImV4dHJhdHJlZXMiLCAtLT4KPCEtLSAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUpIC0tPgoKCjwhLS0gIyBBdmVyYWdlIHRoZSBzdXJ2aXZhbCBtb2RlbHMgLS0+CjwhLS0gZGVhdGhfdGltZXMgPC0gcl9maXQkdW5pcXVlLmRlYXRoLnRpbWVzICAtLT4KPCEtLSBzdXJ2X3Byb2IgPC0gZGF0YS5mcmFtZShyX2ZpdCRzdXJ2aXZhbCkgLS0+CjwhLS0gYXZnX3Byb2IgPC0gc2FwcGx5KHN1cnZfcHJvYixtZWFuKSAtLT4KCjwhLS0gIyBQbG90IHRoZSBzdXJ2aXZhbCBtb2RlbHMgZm9yIGVhY2ggcGF0aWVudCAtLT4KPCEtLSBwbG90KHJfZml0JHVuaXF1ZS5kZWF0aC50aW1lcyxyX2ZpdCRzdXJ2aXZhbFsxLF0sICAtLT4KPCEtLSAgICAgIHR5cGUgPSAibCIsICAtLT4KPCEtLSAgICAgIHlsaW0gPSBjKDAsMSksIC0tPgo8IS0tICAgICAgY29sID0gInJlZCIsIC0tPgo8IS0tICAgICAgeGxhYiA9ICJEYXlzIiwgLS0+CjwhLS0gICAgICB5bGFiID0gInN1cnZpdmFsIiwgLS0+CjwhLS0gICAgICBtYWluID0gIlBhdGllbnQgU3Vydml2YWwgQ3VydmVzIikgLS0+Cgo8IS0tICMgLS0+CjwhLS0gY29scyA8LSBjb2xvcnMoKSAtLT4KPCEtLSBmb3IgKG4gaW4gc2FtcGxlKGMoMjpkaW0odmV0KVsxXSksIDIwKSl7IC0tPgo8IS0tICAgICBsaW5lcyhyX2ZpdCR1bmlxdWUuZGVhdGgudGltZXMsIHJfZml0JHN1cnZpdmFsW24sXSwgdHlwZSA9ICJsIiwgY29sID0gY29sc1tuXSkgLS0+CjwhLS0gfSAtLT4KPCEtLSBsaW5lcyhkZWF0aF90aW1lcywgYXZnX3Byb2IsIGx3ZCA9IDIpIC0tPgo8IS0tIGxlZ2VuZCg1MDAsIDAuNywgbGVnZW5kID0gYygnQXZlcmFnZSA9IGJsYWNrJykpIC0tPgoKCjwhLS0gdmkgPC0gZGF0YS5mcmFtZShzb3J0KHJvdW5kKHJfZml0JHZhcmlhYmxlLmltcG9ydGFuY2UsIDQpLCBkZWNyZWFzaW5nID0gVFJVRSkpIC0tPgo8IS0tIG5hbWVzKHZpKSA8LSAiaW1wb3J0YW5jZSIgLS0+CjwhLS0gaGVhZCh2aSkgLS0+CgoKPCEtLSBjYXQoIlByZWRpY3Rpb24gRXJyb3IgPSAxIC0gSGFycmVsbCdzIGMtaW5kZXggPSAiLCByX2ZpdCRwcmVkaWN0aW9uLmVycm9yKSAtLT4KCgo8IS0tICMgU2V0IHVwIGZvciBnZ3Bsb3QgLS0+CjwhLS0ga21pIDwtIHJlcCgiS00iLGxlbmd0aChrbV9maXQkdGltZSkpIC0tPgo8IS0tIGttX2RmIDwtIGRhdGEuZnJhbWUoa21fZml0JHRpbWUsa21fZml0JHN1cnYsa21pKSAtLT4KPCEtLSBuYW1lcyhrbV9kZikgPC0gYygiVGltZSIsIlN1cnYiLCJNb2RlbCIpIC0tPgoKPCEtLSBjb3hpIDwtIHJlcCgiQ294IixsZW5ndGgoY294X2ZpdCR0aW1lKSkgLS0+CjwhLS0gY294X2RmIDwtIGRhdGEuZnJhbWUoY294X2ZpdCR0aW1lLGNveF9maXQkc3Vydixjb3hpKSAtLT4KPCEtLSBuYW1lcyhjb3hfZGYpIDwtIGMoIlRpbWUiLCJTdXJ2IiwiTW9kZWwiKSAtLT4KCjwhLS0gcmZpIDwtIHJlcCgiUkYiLGxlbmd0aChyX2ZpdCR1bmlxdWUuZGVhdGgudGltZXMpKSAtLT4KPCEtLSByZl9kZiA8LSBkYXRhLmZyYW1lKHJfZml0JHVuaXF1ZS5kZWF0aC50aW1lcyxhdmdfcHJvYixyZmkpIC0tPgo8IS0tIG5hbWVzKHJmX2RmKSA8LSBjKCJUaW1lIiwiU3VydiIsIk1vZGVsIikgLS0+Cgo8IS0tIHBsb3RfZGYgPC0gcmJpbmQoa21fZGYsY294X2RmLHJmX2RmKSAtLT4KCjwhLS0gcCA8LSBnZ3Bsb3QocGxvdF9kZiwgYWVzKHggPSBUaW1lLCB5ID0gU3VydiwgY29sb3IgPSBNb2RlbCkpIC0tPgo8IS0tIHAgKyBnZW9tX2xpbmUoKSAtLT4KCgoKCjwhLS0gIyMjIyMjIyMjIyMjIC0tPgoKCgoKCjwhLS0gaW5zdGFsbC5wYWNrYWdlcygiT0lzdXJ2IikgLS0+CjwhLS0gbGlicmFyeShPSXN1cnYpIC0tPgoKPCEtLSBsaWJyYXJ5KGhlbHA9S01zdXJ2KSAtLT4KCjwhLS0gZGF0YShhaWRzKSAtLT4KPCEtLSBnbGltcHNlKGFpZHMpIC0tPgoKCjwhLS0gZGF0YSh0b25ndWUpIC0tPgoKPCEtLSBnbGltcHNlKHRvbmd1ZSkgLS0+Cgo8IS0tIG15LnN1cnYub2JqZWN0IDwtIFN1cnYodG9uZ3VlJHRpbWVbdG9uZ3VlJHR5cGU9PTFdLCB0b25ndWUkZGVsdGFbdG9uZ3VlJHR5cGU9PTFdKSAtLT4KCjwhLS0gbXkuc3Vydi5vYmplY3QgLS0+Cgo8IS0tIGRhdGEocHN5Y2gpIC0tPgoKPCEtLSBteS5zdXJ2Lm9iamVjdDIgPC0gU3Vydihwc3ljaCRhZ2UsIHBzeWNoJGFnZStwc3ljaCR0aW1lLCBwc3ljaCRkZWF0aCkgLS0+Cgo8IS0tIG15LnN1cnYub2JqZWN0MiAtLT4KCgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gbGlicmFyeSgic3Vydml2YWwiKSAtLT4KPCEtLSBmaXQgPC0gc3VydmZpdChTdXJ2KHRpbWUsc3RhdHVzKSAtLT4KPCEtLSB+IHNleCwgZGF0YSA9IGx1bmcpIC0tPgo8IS0tIGNsYXNzKGZpdCkgLS0+CjwhLS0gIyMgWzFdICJzdXJ2Zml0IiAtLT4KPCEtLSBsaWJyYXJ5KCJzdXJ2bWluZXIiKSAtLT4KPCEtLSBnZ3N1cnZwbG90KGZpdCwgZGF0YSA9IGx1bmcpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBnZ3N1cnZwbG90KGZpdCwgZGF0YSA9IGx1bmcsIGZ1biA9ICJldmVudCIpIC0tPgoKPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZ2dzdXJ2cGxvdChmaXQsIGRhdGEgPSBsdW5nLCBmdW4gPSAiY3VtaGF6IikgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZ2dzdXJ2cGxvdChmaXQsIGRhdGEgPSBsdW5nLCAtLT4KPCEtLSBjb25mLmludCA9IFRSVUUsIC0tPgo8IS0tIHB2YWwgPSBUUlVFLCAtLT4KPCEtLSBmdW4gPSAicGN0IiwgLS0+CjwhLS0gcmlzay50YWJsZSA9IFRSVUUsIC0tPgo8IS0tIHRhYmxlcy5oZWlnaHQgPSAwLjMsIC0tPgo8IS0tIHNpemUgPSAwLjgsIC0tPgo8IS0tIGxpbmV0eXBlID0gInN0cmF0YSIsIC0tPgo8IS0tIHBhbGV0dGUgPSBjKCIjRTdCODAwIiwgLS0+CjwhLS0gIiMyRTlGREYiKSwgLS0+CjwhLS0gbGVnZW5kID0gInRvcCIsIC0tPgo8IS0tIGxlZ2VuZC50aXRsZSA9ICJTZXgiLCAtLT4KPCEtLSBsZWdlbmQubGFicyA9IGMoIk1hbGUiLCAtLT4KPCEtLSAiRmVtYWxlIiksIC0tPgo8IS0tIGNleCA9IDAuMiAtLT4KPCEtLSApIC0tPgo8IS0tIGBgYCAtLT4KCjwhLS0gYGBge3J9IC0tPgo8IS0tIGxpYnJhcnkoInN1cnZpdmFsIikgLS0+CjwhLS0gZml0IDwtIGNveHBoKFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCArIGFnZSwgZGF0YSA9IGx1bmcpIC0tPgo8IS0tIGZ0ZXN0IDwtIGNveC56cGgoZml0KSAtLT4KPCEtLSBmdGVzdCAtLT4KPCEtLSBgYGAgLS0+Cgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBsaWJyYXJ5KCJzdXJ2bWluZXIiKSAtLT4KPCEtLSBnZ2NveHpwaChmdGVzdCkgLS0+CjwhLS0gYGBgIC0tPgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tIGxpYnJhcnkoInN1cnZpdmFsIikgLS0+CjwhLS0gbGlicmFyeSgic3Vydm1pbmVyIikgLS0+CjwhLS0gZml0IDwtIGNveHBoKFN1cnYodGltZSwgc3RhdHVzKSB+IC0tPgo8IS0tIHNleCArIGFnZSwgZGF0YSA9IGx1bmcpIC0tPgoKPCEtLSBgYGAgLS0+CgoKCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBnZ2NveGRpYWdub3N0aWNzKGZpdCwgLS0+CjwhLS0gdHlwZSA9ICJkZXZpYW5jZSIsIC0tPgo8IS0tIG94LnNjYWxlID0gImxpbmVhci5wcmVkaWN0aW9ucyIpIC0tPgoKPCEtLSBgYGAgLS0+CgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tIGdnY294ZGlhZ25vc3RpY3MoZml0LCAtLT4KPCEtLSB0eXBlID0gInNjaG9lbmZlbGQiLCAtLT4KPCEtLSBveC5zY2FsZSA9ICJ0aW1lIikgLS0+CjwhLS0gYGBgIC0tPgoKCgoKPCEtLSAjIEFuYWx5c2lzIC0tPgoKPCEtLSAjIyBTdXJ2aXZhbCBBbmFseXNpcyAtLT4KCjwhLS0gaHR0cHM6Ly9naXRodWIuY29tL2RhdGFjYW1wL3R1dG9yaWFsIC0tPgoKPCEtLSBCYXNlZCBvbiBodHRwczovL3d3dy5kYXRhY2FtcC5jb20vY29tbXVuaXR5L3R1dG9yaWFscy9zdXJ2aXZhbC1hbmFseXNpcy1SIC0tPgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tIGxpYnJhcnkodHV0b3JpYWwpIC0tPgo8IS0tIGxpYnJhcnkoc3Vydml2YWwpIC0tPgo8IS0tIGxpYnJhcnkoc3Vydm1pbmVyKSAtLT4KPCEtLSBsaWJyYXJ5KHRpZHl2ZXJzZSkgLS0+CjwhLS0gbGlicmFyeShqbXYpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBkYXRhKG92YXJpYW4pIC0tPgo8IS0tIGdsaW1wc2Uob3ZhcmlhbikgLS0+CjwhLS0gaGVscChvdmFyaWFuKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gc3VtbWFyeShvdmFyaWFuKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gdmFyT3ZhcmlhbiA8LSBuYW1lcyhvdmFyaWFuKSAtLT4KCjwhLS0gb3ZhcmlhbjIgPC0gb3ZhcmlhbiAlPiUgIC0tPgo8IS0tICAgICBtYXBfZGYoYXMuZmFjdG9yKSAtLT4KCjwhLS0gam12OjpkZXNjcmlwdGl2ZXMob3ZhcmlhbiwgdmFyT3ZhcmlhbiwgZnJlcSA9IFRSVUUpIC0tPgoKPCEtLSBqbXY6OmRlc2NyaXB0aXZlcyhvdmFyaWFuMiwgdmFyT3ZhcmlhbiwgZnJlcSA9IFRSVUUpIC0tPgoKPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyBEaWNob3RvbWl6ZSBhZ2UgYW5kIGNoYW5nZSBkYXRhIGxhYmVscyAtLT4KPCEtLSBvdmFyaWFuJHJ4IDwtIGZhY3RvcihvdmFyaWFuJHJ4LCAgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiMSIsICIyIiksICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJBIiwgIkIiKSkgLS0+CjwhLS0gb3ZhcmlhbiRyZXNpZC5kcyA8LSBmYWN0b3Iob3ZhcmlhbiRyZXNpZC5kcywgIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIjEiLCAiMiIpLCAgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygibm8iLCAieWVzIikpIC0tPgo8IS0tIG92YXJpYW4kZWNvZy5wcyA8LSBmYWN0b3Iob3ZhcmlhbiRlY29nLnBzLCAgLS0+CjwhLS0gICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIxIiwgIjIiKSwgIC0tPgo8IS0tICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiZ29vZCIsICJiYWQiKSkgLS0+Cgo8IS0tIGptdjo6ZGVzY3JpcHRpdmVzKG92YXJpYW4sIHZhck92YXJpYW4sIGZyZXEgPSBUUlVFKSAtLT4KCjwhLS0gYGBgIC0tPgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tICMgRGF0YSBzZWVtcyB0byBiZSBiaW1vZGFsIC0tPgo8IS0tIGhpc3Qob3ZhcmlhbiRhZ2UpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBvdmFyaWFuIDwtIG92YXJpYW4gJT4lIG11dGF0ZShhZ2VfZ3JvdXAgPSBpZmVsc2UoYWdlID49IDUwLCAib2xkIiwgInlvdW5nIikpIC0tPgo8IS0tIG92YXJpYW4kYWdlX2dyb3VwIDwtIGZhY3RvcihvdmFyaWFuJGFnZV9ncm91cCkgLS0+Cgo8IS0tIHZhck92YXJpYW4gPC0gbmFtZXMob3ZhcmlhbikgLS0+Cgo8IS0tIGptdjo6ZGVzY3JpcHRpdmVzKG92YXJpYW4sIHZhck92YXJpYW4sIGZyZXEgPSBUUlVFKSAtLT4KPCEtLSBgYGAgLS0+CgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyBGaXQgc3Vydml2YWwgZGF0YSB1c2luZyB0aGUgS2FwbGFuLU1laWVyIG1ldGhvZCAtLT4KPCEtLSBzdXJ2X29iamVjdCA8LSBTdXJ2KHRpbWUgPSBvdmFyaWFuJGZ1dGltZSwgZXZlbnQgPSBvdmFyaWFuJGZ1c3RhdCkgLS0+CjwhLS0gc3Vydl9vYmplY3QgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gZml0MSA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gcngsIGRhdGEgPSBvdmFyaWFuKSAtLT4KPCEtLSBzdW1tYXJ5KGZpdDEpIC0tPgo8IS0tIGBgYCAtLT4KCgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBnZ3N1cnZwbG90KGZpdDEsIGRhdGEgPSBvdmFyaWFuLCBwdmFsID0gVFJVRSkgLS0+CjwhLS0gYGBgIC0tPgoKCjwhLS0gYGBge3J9IC0tPgo8IS0tICMgRXhhbWluZSBwcmRpY3RpdmUgdmFsdWUgb2YgcmVzaWR1YWwgZGlzZWFzZSBzdGF0dXMgLS0+CjwhLS0gZml0MiA8LSBzdXJ2Zml0KHN1cnZfb2JqZWN0IH4gcmVzaWQuZHMsIGRhdGEgPSBvdmFyaWFuKSAtLT4KPCEtLSBnZ3N1cnZwbG90KGZpdDIsIGRhdGEgPSBvdmFyaWFuLCBwdmFsID0gVFJVRSkgLS0+CjwhLS0gYGBgIC0tPgoKPCEtLSBgYGB7cn0gLS0+CjwhLS0gIyBGaXQgYSBDb3ggcHJvcG9ydGlvbmFsIGhhemFyZHMgbW9kZWwgLS0+CjwhLS0gZml0LmNveHBoIDwtIGNveHBoKHN1cnZfb2JqZWN0IH4gcnggKyByZXNpZC5kcyArIGFnZV9ncm91cCArIGVjb2cucHMsICAtLT4KPCEtLSAgICAgICAgICAgICAgICAgICAgZGF0YSA9IG92YXJpYW4pIC0tPgo8IS0tIGdnZm9yZXN0KGZpdC5jb3hwaCwgZGF0YSA9IG92YXJpYW4pICsgLS0+CjwhLS0gICAgIGdlb21fZXJyb3JiYXIobmEucm0gPSBUUlVFKSAtLT4KPCEtLSBgYGAgLS0+CgoKCiMgT3BlbkludHJvIFN0YXRpc3RpY3MgCgpodHRwczovL3d3dy5vcGVuaW50cm8ub3JnL3N0YXQvc3Vydi5waHAKCmh0dHBzOi8vd3d3Lm9wZW5pbnRyby5vcmcvZG93bmxvYWQucGhwP2ZpbGU9c3Vydml2YWxfYW5hbHlzaXNfaW5fUiZyZWZlcnJlcj0vc3RhdC9zdXJ2LnBocAoKaHR0cHM6Ly93d3cub3BlbmludHJvLm9yZy9kb3dubG9hZC5waHA/ZmlsZT1zdXJ2aXZhbF9hbmFseXNpc19pbl9SX2NvZGUmcmVmZXJyZXI9L3N0YXQvc3Vydi5waHAKCmh0dHBzOi8vd3d3Lm9wZW5pbnRyby5vcmcvZG93bmxvYWQucGhwP2ZpbGU9c3Vydml2YWxfYW5hbHlzaXNfaW5fUl9jb2RlX2RmLWNwJnJlZmVycmVyPS9zdGF0L3N1cnYucGhwCgoKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcygiT0lzdXJ2IikKYGBgCgoKYGBge3J9CiMgbGlicmFyeShPSXN1cnYpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkoc3BsaW5lcykKbGlicmFyeShLTXN1cnYpCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KGhlbHA9S01zdXJ2KQpgYGAKCgpgYGB7cn0KZGF0YShhaWRzKQphaWRzCmBgYAoKYGBge3J9CiBkYXRhKHRvbmd1ZSkKdG9uZ3VlCmBgYAoKCmBgYHtyfQpteS5zdXJ2Lm9iamVjdCA8LSBTdXJ2KHRvbmd1ZSR0aW1lW3Rvbmd1ZSR0eXBlPT0xXSwgdG9uZ3VlJGRlbHRhW3Rvbmd1ZSR0eXBlPT0xXSkKbXkuc3Vydi5vYmplY3QKYGBgCgoKYGBge3J9CmRhdGEocHN5Y2gpCnBzeWNoCm15LnN1cnYub2JqZWN0IDwtIFN1cnYocHN5Y2gkYWdlLCBwc3ljaCRhZ2UgKyBwc3ljaCR0aW1lLCBwc3ljaCRkZWF0aCkKbXkuc3Vydi5vYmplY3QKCmBgYAoKCgoKCgoKCmBgYHtyfQpybShsaXN0PWxzKCkpCgojPT09PiBsb2FkaW5nIHBhY2thZ2VzIGFuZCBzdWNoIDw9PT0jCiNpbnN0YWxsLnBhY2thZ2VzKCJPSXN1cnYiKQpsaWJyYXJ5KE9Jc3VydikKZGF0YShhaWRzKQphaWRzCmF0dGFjaChhaWRzKQppbmZlY3QKZGV0YWNoKGFpZHMpCmFpZHMkaW5mZWN0CgojPT09PiBzdXJ2aXZhbCBvYmplY3QgPD09PSMKZGF0YSh0b25ndWUpOyBhdHRhY2godG9uZ3VlKSAgICMgdGhlIGZvbGxvd2luZyB3aWxsIG5vdCBhZmZlY3QgY29tcHV0YXRpb25zCiMgY3JlYXRlIGEgc3Vic2V0IGZvciBqdXN0IHRoZSBmaXJzdCBncm91cCBieSB1c2luZyBbdHlwZT09MV0KbXkuc3Vydi5vYmplY3QgPC0gU3Vydih0aW1lW3R5cGU9PTFdLCBkZWx0YVt0eXBlPT0xXSkKbXkuc3Vydi5vYmplY3QKZGV0YWNoKHRvbmd1ZSkKCmRhdGEocHN5Y2gpOyBhdHRhY2gocHN5Y2gpCm15LnN1cnYub2JqZWN0IDwtIFN1cnYoYWdlLCBhZ2UrdGltZSwgZGVhdGgpCm15LnN1cnYub2JqZWN0CmRldGFjaChwc3ljaCkKCiM9PT0+IEstTSBFc3RpbWF0ZSA8PT09IwpkYXRhKHRvbmd1ZSk7IGF0dGFjaCh0b25ndWUpCm15LnN1cnYgPC0gU3Vydih0aW1lW3R5cGU9PTFdLCBkZWx0YVt0eXBlPT0xXSkKc3VydmZpdChteS5zdXJ2IH4gMSkKbXkuZml0IDwtIHN1cnZmaXQobXkuc3VydiB+IDEpCnN1bW1hcnkobXkuZml0KSRzdXJ2ICAgICAjIHJldHVybnMgdGhlIEthcGxhbi1NZWllciBlc3RpbWF0ZSBhdCBlYWNoIHRfaQpzdW1tYXJ5KG15LmZpdCkkdGltZSAgICAgIyB7dF9pfQpzdW1tYXJ5KG15LmZpdCkkbi5yaXNrICAgIyB7WV9pfQpzdW1tYXJ5KG15LmZpdCkkbi5ldmVudCAgIyB7ZF9pfQpzdW1tYXJ5KG15LmZpdCkkc3RkLmVyciAgIyBzdGFuZGFyZCBlcnJvciBvZiB0aGUgSy1NIGVzdGltYXRlIGF0IHt0X2l9CnN1bW1hcnkobXkuZml0KSRsb3dlciAgICAjIGxvd2VyIHBvaW50d2lzZSBlc3RpbWF0ZXMgKGFsdGVybmF0aXZlbHksICR1cHBlcikKc3RyKG15LmZpdCkgICAgICAgICAgICAgICMgZnVsbCBzdW1tYXJ5IG9mIHRoZSBteS5maXQgb2JqZWN0CnN0cihzdW1tYXJ5KG15LmZpdCkpICAgICAjIGZ1bGwgc3VtbWFyeSBvZiB0aGUgbXkuZml0IG9iamVjdApwZGYoIi4uL2ZpZ3VyZXMva21QbG90LnBkZiIsIDcsIDQuNSkKcGxvdChteS5maXQsIG1haW49IkthcGxhbi1NZWllciBlc3RpbWF0ZSB3aXRoIDk1JSBjb25maWRlbmNlIGJvdW5kcyIsCiAgIHhsYWI9InRpbWUiLCB5bGFiPSJzdXJ2aXZhbCBmdW5jdGlvbiIpCmRldi5vZmYoKQpteS5maXQxIDwtIHN1cnZmaXQoIFN1cnYodGltZSwgZGVsdGEpIH4gdHlwZSApICAgIyBoZXJlIHRoZSBrZXkgaXMgInR5cGUiCmRldGFjaCh0b25ndWUpCgojPT09PiBjb25maWRlbmNlIGJhbmRzIDw9PT0jCmRhdGEoYm10KTsgYXR0YWNoKGJtdCkKbXkuc3VydiA8LSBTdXJ2KHQyW2dyb3VwPT0xXSwgZDNbZ3JvdXA9PTFdKQpteS5jYiA8LSBjb25mQmFuZHMobXkuc3VydiwgY29uZkxldmVsPTAuOTUsIHR5cGU9ImhhbGwiKQpwZGYoIi4uL2ZpZ3VyZXMvY29uZkJhbmQucGRmIiwgOCwgNSkKcGxvdChzdXJ2Zml0KG15LnN1cnYgfiAxKSwgeGxpbT1jKDEwMCwgNjAwKSwgeGxhYj0idGltZSIsCiAgeWxhYj0iRXN0aW1hdGVkIFN1cnZpdmFsIEZ1bmN0aW9uIiwKICBtYWluPSJSZXByb2R1Y2luZyBDb25maWRlbmNlIEJhbmRzIGZvciBFeGFtcGxlIDQuMiBpbiBLbGVpbi9Nb2VzY2hiZXJnZXIiKQoKbGluZXMobXkuY2IkdGltZSwgbXkuY2IkbG93ZXIsIGx0eT0zLCB0eXBlPSJzIikKbGluZXMobXkuY2IkdGltZSwgbXkuY2IkdXBwZXIsIGx0eT0zLCB0eXBlPSJzIikKbGVnZW5kKDEwMCwgMC4zLCBsZWdlbmQ9YygiSy1NIHN1cnZpdmFsIGVzdGltYXRlIiwKICAicG9pbnR3aXNlIGludGVydmFscyIsImNvbmZpZGVuY2UgYmFuZHMiKSwgbHR5PTE6MykKZGV2Lm9mZigpCmRldGFjaChibXQpCgoKIz09PT4gY3VtdWxhdGl2ZSBoYXphcmQgPD09PSMKZGF0YSh0b25ndWUpOyBhdHRhY2godG9uZ3VlKQpteS5zdXJ2IDwtIFN1cnYodGltZVt0eXBlPT0xXSwgZGVsdGFbdHlwZT09MV0pCm15LmZpdCAgPC0gc3VtbWFyeShzdXJ2Zml0KG15LnN1cnYgfiAxKSkKSC5oYXQgICA8LSAtbG9nKG15LmZpdCRzdXJ2KQpILmhhdCAgIDwtIGMoSC5oYXQsIHRhaWwoSC5oYXQsIDEpKQpoLnNvcnQub2YgPC0gbXkuZml0JG4uZXZlbnQgLyBteS5maXQkbi5yaXNrCkgudGlsZGUgICA8LSBjdW1zdW0oaC5zb3J0Lm9mKQpILnRpbGRlICAgPC0gYyhILnRpbGRlLCB0YWlsKEgudGlsZGUsIDEpKQpwZGYoIi4uL2ZpZ3VyZXMvY3VtSGF6YXJkLnBkZiIsIDYsIDQpCnBsb3QoYyhteS5maXQkdGltZSwgMjUwKSwgSC5oYXQsIHhsYWI9InRpbWUiLCB5bGFiPSJjdW11bGF0aXZlIGhhemFyZCIsCiAgbWFpbj0iY29tcGFyaW5nIGN1bXVsYXRpdmUgaGF6YXJkcyIsIHlsaW09cmFuZ2UoYyhILmhhdCwgSC50aWxkZSkpLCB0eXBlPSJzIikKcG9pbnRzKGMobXkuZml0JHRpbWUsIDI1MCksIEgudGlsZGUsIGx0eT0yLCB0eXBlPSJzIikKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kPWMoIkguaGF0IiwiSC50aWxkZSIpLCBsdHk9MToyKQpkZXYub2ZmKCkKZGV0YWNoKHRvbmd1ZSkKCgojPT09PiBtZWFuL21lZGlhbiA8PT09IwpkYXRhKGRydWc2bXApOyBhdHRhY2goZHJ1ZzZtcCkKbXkuc3VydiA8LSBTdXJ2KHQxLCByZXAoMSwgMjEpKSAgICMgYWxsIHBsYWNlYm8gcGF0aWVudHMgb2JzZXJ2ZWQKc3VydmZpdChteS5zdXJ2IH4gMSkKcHJpbnQoc3VydmZpdChteS5zdXJ2IH4gMSksIHByaW50LnJtZWFuPVRSVUUpCmRldGFjaChkcnVnNm1wKQoKIz09PT4gdGVzdCBmb3IgMisgc2FtcGxlcyA8PT09IwpkYXRhKGJ0cmlhbCk7IGF0dGFjaChidHJpYWwpCnN1cnZkaWZmKFN1cnYodGltZSwgZGVhdGgpIH4gaW0pICAgIyBvdXRwdXQgb21pdHRlZApzdXJ2ZGlmZihTdXJ2KHRpbWUsIGRlYXRoKSB+IGltLCByaG89MSkgICAjIG91dHB1dCBvbWl0dGVkCmRldGFjaChidHJpYWwpCgojPT09PiBjb3hwaCwgdGltZS1pbmRlcGVuZGVudCA8PT09IwpkYXRhKGJ1cm4pOyBhdHRhY2goYnVybikKbXkuc3VydiAgIDwtIFN1cnYoVDEsIEQxKQpjb3hwaC5maXQgPC0gY294cGgobXkuc3VydiB+IFoxICsgYXMuZmFjdG9yKFoxMSksIG1ldGhvZD0iYnJlc2xvdyIpCmNveHBoLmZpdApjbyA8LSBjb3hwaC5maXQkY29lZmZpY2llbnRzICAjIG1heSB1c2UgY294cGguZml0JGNvZWZmIGluc3RlYWQKdmEgPC0gY294cGguZml0JHZhciAgICAgICAgICAgIyBJXigtMSksIGVzdGltYXRlZCBjb3YgbWF0cml4IG9mIHRoZSBlc3RpbWF0ZXMKbGwgPC0gY294cGguZml0JGxvZ2xpayAgICAgICAgIyBsb2ctbGlrZWxpaG9vZCBmb3IgYWx0IGFuZCBudWxsIE1MRXMsIHJlc3AuCm15LnN1cnZmaXQub2JqZWN0IDwtIHN1cnZmaXQoY294cGguZml0KQpob2xkIDwtIHN1cnZmaXQobXkuc3VydiB+IDEpCiNzb3VyY2UoImh0dHA6Ly93d3cuc3RhdC51Y2xhLmVkdS9+ZGF2aWQvdGVhYy9zdXJ2L2xvY2FsLWNveHBoLXRlc3QuUiIpCmNveHBoLmZpdApDICAgPC0gbWF0cml4KGMoMCwgMSwgMCwgMCwKICAgICAgICAgICAgICAgIDAsIDAsIDEsIDAsCiAgICAgICAgICAgICAgICAwLCAwLCAwLCAxKSwgbnJvdz0zLCBieXJvdz1UUlVFKQpkICAgPC0gcmVwKDAsIDMpCnQxICA8LSBDICUqJSBjbyAtIGQKdDIgIDwtIEMgJSolIHZhICUqJSB0KEMpClhXMiA8LSBjKHQodDEpICUqJSBzb2x2ZSh0MikgJSolIHQxKQpwY2hpc3EoWFcyLCAzLCBsb3dlci50YWlsPUZBTFNFKQojbG9jYWwuY294cGgudGVzdChjb3hwaC5maXQsIDI6NCkKbXkuc3VydmZpdC5vYmplY3QgPC0gc3VydmZpdChjb3hwaC5maXQpCmRldGFjaChidXJuKQoKCiM9PT0+IGNveHBoLCB0aW1lLWRlcGVuZGVudCA8PT09IwpkYXRhKHJlbGFwc2UpCnJlbGFwc2UKCk4gIDwtIGRpbShyZWxhcHNlKVsxXQp0MSA8LSByZXAoMCwgTitzdW0oIWlzLm5hKHJlbGFwc2UkaW50KSkpICAjIGluaXRpYWxpemUgc3RhcnQgdGltZSBhdCAwCnQyIDwtIHJlcCgtMSwgbGVuZ3RoKHQxKSkgICAgICAgICAgICAgICAgICMgYnVpbGQgdmVjdG9yIGZvciBlbmQgdGltZXMKZCAgPC0gcmVwKC0xLCBsZW5ndGgodDEpKSAgICAgICAgICAgICAgICAgIyB3aGV0aGVyIGV2ZW50IHdhcyBjZW5zb3JlZApnICA8LSByZXAoLTEsIGxlbmd0aCh0MSkpICAgICAgICAgICAgICAgICAjIGdlbmRlciBjb3ZhcmlhdGUKaSAgPC0gcmVwKEZBTFNFLCBsZW5ndGgodDEpKSAgICAgICAgICAgICAgIyBpbml0aWFsaXplIGludGVydmVudGlvbiBhdCBGQUxTRQoKaiAgPC0gMQpmb3IoaWkgaW4gMTpkaW0ocmVsYXBzZSlbMV0pewogIGlmKGlzLm5hKHJlbGFwc2UkaW50W2lpXSkpeyAgICAgICMgbm8gaW50ZXJ2ZW50aW9uLCBjb3B5IHN1cnZpdmFsIHJlY29yZAogICAgdDJbal0gPC0gcmVsYXBzZSRldmVudFtpaV0KICAgIGRbal0gIDwtIHJlbGFwc2UkZGVsdGFbaWldCiAgICBnW2pdICA8LSByZWxhcHNlJGdlbmRlcltpaV0KICAgIGogPC0gaisxCiAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbnRlcnZlbnRpb24sIHNwbGl0IHJlY29yZHMKICAgIGdbaiswOjFdIDwtIHJlbGFwc2UkZ2VuZGVyW2lpXSAjIGdlbmRlciBpcyBzYW1lIGZvciBlYWNoIHRpbWUKICAgIGRbal0gICAgIDwtIDAgICAgICAgICAgICAgICAgICAjIG5vIHJlbGFwc2Ugb2JzZXJ2ZWQgcHJlLWludGVydmVudGlvbgogICAgZFtqKzFdICAgPC0gcmVsYXBzZSRkZWx0YVtpaV0gICMgcmVsYXBzZSBvY2N1ciBwb3N0LWludGVydmVudGlvbj8KICAgIGlbaisxXSAgIDwtIFRSVUUgICAgICAgICAgICAgICAjIGludGVydmVudGlvbiBjb3ZhcmlhdGUsIHBvc3QtaW50ZXJ2ZW50aW9uCiAgICB0MltqXSAgICA8LSByZWxhcHNlJGludFtpaV0tMSAgIyBlbmQgb2YgcHJlLWludGVydmVudGlvbgogICAgdDFbaisxXSAgPC0gcmVsYXBzZSRpbnRbaWldLTEgICMgc3RhcnQgb2YgcG9zdC1pbnRlcnZlbnRpb24KICAgIHQyW2orMV0gIDwtIHJlbGFwc2UkZXZlbnRbaWldICAjIGVuZCBvZiBwb3N0LWludGVydmVudGlvbgogICAgaiA8LSBqKzIgICAgICAgICAgICAgICAgICAgICAgICMgdHdvIHJlY29yZHMgYWRkZWQKICB9Cn0KCm15U3VydiA8LSBTdXJ2KHQxLCB0MiwgZCkgICAgICAgICMgcGcgMyBkaXNjdXNzZXMgbGVmdC10cnVuYy4gcmlnaHQtY2Vucy4gZGF0YQpteUNQSCAgPC0gY294cGgobXlTdXJ2IH4gZyArIGkpCgojZGF0YShidXJuKTsgYXR0YWNoKGJ1cm4pCiMjc291cmNlKCJodHRwOi8vd3d3LnN0YXQudWNsYS5lZHUvfmRhdmlkL3RlYWMvc3Vydi90aW1lLWRlcC1jb3hwaC5SIikKI3RkLmNveHBoIDwtIHRpbWVEZXBDb3hwaChidXJuLCAiVDEiLCAiRDEiLCAyOjQsICJaMSIsIHZlcmJvc2U9RkFMU0UpCiN0ZC5jb3hwaCAgICMgc29tZSBtb2RlbCBvdXRwdXQgaXMgb21pdHRlZCBmb3IgYnJldml0eQojZGV0YWNoKGJ1cm4pCgojPT09PiBBRlQgbW9kZWxzIDw9PT0jCmRhdGEobGFyeW54KQphdHRhY2gobGFyeW54KQpzckZpdCA8LSBzdXJ2cmVnKFN1cnYodGltZSwgZGVsdGEpIH4gYXMuZmFjdG9yKHN0YWdlKSArIGFnZSwgZGlzdD0id2VpYnVsbCIpCnN1bW1hcnkoc3JGaXQpCnNyRml0RXhwIDwtIHN1cnZyZWcoU3Vydih0aW1lLCBkZWx0YSkgfiBhcy5mYWN0b3Ioc3RhZ2UpICsgYWdlLCBkaXN0PSJleHBvbmVudGlhbCIpCnN1bW1hcnkoc3JGaXRFeHApCnNyRml0RXhwJGNvZWZmICAgICMgY292YXJpYXRlIGNvZWZmaWNpZW50cwpzckZpdEV4cCRpY29lZiAgICAjIGludGVyY2VwdCBhbmQgc2NhbGUgY29lZmZpY2llbnRzCnNyRml0RXhwJHZhciAgICAgICMgdmFyaWFuY2UtY292YXJpYW5jZSBtYXRyaXgKc3JGaXRFeHAkbG9nbGlrICAgIyBsb2ctbGlrZWxpaG9vZApzckZpdCRzY2FsZSAgICAgICAjIG5vdCB1c2luZyBzckZpdEV4cCAoZGVmYXVsdGVkIHRvIDEpCmRldGFjaChsYXJ5bngpCgpgYGAKCgoKCmBgYHtyfQoKIyBQb3N0ZWQgd2l0aCBwZXJtaXNzaW9uIG9mIHRoZSBjb2RlIGF1dGhvcjoKIyBCZWF1IEJlbmphbWluIEJydWNlCiMgQXV0aG9yIGVtYWlsOiBiYmJydWNlQGVtb3J5LmVkdQojIAojIFRoaXMgY29kZSBpcyBhdmFpbGFibGUgdW5kZXIgR1BMLTIKIyBGb3IgbGljZW5zZSBpbmZvcm1hdGlvbiwgc2VlCiMgaHR0cDovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvbGljZW5zZXMvR1BMLTIKCmxpYnJhcnkoS01zdXJ2KQpkYXRhKGJ1cm4pCgojPT09PT0+IENvbnZlcnQgYSBkYXRhIGZyYW1lIHRvIGEgY291bnRpbmcgcHJvY2VzcyB2ZXJzaW9uIDw9PT09PSMKIz09PT09PiBBbGxvd3MgZm9yIHRpbWUgZGVwZW5kZW50IHZhcmlhYmxlcyB0byBiZSBpbnRyb2R1Y2VkIDw9PT09PSMKZGYuY3AgPSBmdW5jdGlvbihkYXRhLHQudmFyLHN0YXR1cy52YXIsY292YXJzPXNldGRpZmYobmFtZXMoZGF0YSksYyh0LnZhcixzdGF0dXMudmFyKSkpIHsKICAjIGRhdGE6IGRhdGEgZnJhbWUgdGhhdCByZXByZXNlbnRzIHRoZSBkYXRhc2V0CiAgIyB0LnZhcjogdGhlIGNvbHVtbiBuYW1lIG9mICJkYXRhIiB0aGF0IHJlcHJlc2VudHMgdGhlIHN1cnZpdmFsIHRpbWUgdmFyaWFibGUKICAjIHN0YXR1cy52YXI6IHRoZSBjb2x1bW4gbmFtZSBvZiAiZGF0YSIgdGhhdCByZXByZXNlbnRzIHRoZSBzdGF0dXMgdmFyaWFibGUKICAjIGNvdmFyczogbGlzdCBvdGhlciBjb3ZhcmlhdGVzIHRvIHJldGFpbgogIAogICMgUmV0dXJuZWQgb2JqZWN0OiBhIGRhdGEgZnJhbWUgdGhhdCBicmVha3MgZWFjaCBldmVudCBkb3duIHRvIGEgY291bnRpbmcgcHJvY2VzcwogIAogICMgc29ydGVkIHRpbWVzLCBhcHBlbmQgdG8gMAogIHQuc29ydCA8LSBjKDAsc29ydCh1bmxpc3QodW5pcXVlKGRhdGFbdC52YXJdKSkpKQogIAogICMgZm9yIGVhY2ggZGF0YSBwb2ludCBmaW5kIHRpbWVzIGxlc3MgdGhhbiBvciBlcXVhbCB0byB0aGUgb2JzJyB0aW1lCiAgdC5saXN0IDwtIGxhcHBseSh1bmxpc3QoZGF0YVt0LnZhcl0pLGZ1bmN0aW9uKHgpIHQuc29ydFt0LnNvcnQ8PXhdKQogIAogICMgY3JlYXRlIGEgbGlzdCBvZiBkYXRhc2V0cyB3aXRoIGNvdmFyaWF0ZXMgYW5kIGFsbCByZWxldmFudCBzdGFydC9zdG9wIHRpbWVzCiAgIyB1c2Ugd2l0aCB0byBzZXQgdGhlIGVudmlyb25tZW50IHRvIHRoZSBjb3JyZWN0IGxpc3QgaXRlbQogIGRmLmxpc3QgPC0gbGFwcGx5KHNlcV9hbG9uZyh0Lmxpc3QpLGZ1bmN0aW9uKGkpIGNiaW5kKHdpdGgobGlzdCh4PXQubGlzdFtbaV1dKSwKICAgICAgICAgICAgICAgICAgICAgIyBzdGFydCBieSByZW1vdmluZyBvbmUgZnJvbSBlbmQgb2YgeCwgc3RvcCBieSByZW1vdmluZyBmaXJzdCBvZiB4CiAgICAgICAgICAgICAgICAgICAgICMgaW5jbHVkZSB0aGUgc3RhdHVzIHZhcmlhYmxlIGluIHRoZSBkYXRhZnJhbWUgLSBoZWxwZnVsIGxhdGVyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICBkYXRhLmZyYW1lKHN0YXJ0PWhlYWQoeCwtMSksc3RvcD10YWlsKHgsLTEpLGRhdGFbaSxjKHN0YXR1cy52YXIsY292YXJzKV0pKSkpCgogICMgZG8uY2FsbCB1c2VzIGRmLmxpc3QgYXMgdGhlIGFyZ3VtZW50IGZvciByYmluZAogIGRmIDwtIGRvLmNhbGwocmJpbmQsZGYubGlzdCkKCiAgIyBjcmVhdGUgdGhlIGNvcnJlY3Qgc3RhdHVzIG5lZWQgbGFzdCB0aW1lIGZvciBlYWNoCiAgIyBzdWJqZWN0IHdpdGggc3RhdHVzPTEgdG8gdG8gYmUgc3RhdHVzPTEgYnV0IGFsbCBvdGhlcnMgc3RhdHVzPTAKICAjCiAgIyB0aGUgbGFwcGx5IGNyZWF0ZXMgdmVjdG9ycyAwLDAsMCwuLi4sMSBiYXNlZCBvbiBsZW5ndGggb2YgdC5saXN0CiAgIyBuZWVkIHRvIHN1YnN0cmFjdCAyIGJlY2F1c2UgdGhlIGxhZyB0YWtlcyBvbmUgYXdheSwgdGhlbiBuZWVkIG9uZSBmb3IgdGhlIDEgYXQgZW5kCiAgIyBkby5jYWxsIHdpdGggYyBiaW5kcyB0aGVtIHRvZ2V0aGVyIGludG8gYSBzaW5nbGUgdmVjdG9yCiAgIyB0aGlzIGlzIHRoZW4gbXVsdGlwbGllZCBieSBzdGF0dXMgdG8gY29ycmVjdCBpdAogIGtlZXAuc3RhdHVzIDwtIGRvLmNhbGwoYyxsYXBwbHkodC5saXN0LGZ1bmN0aW9uKHgpIGMocmVwKDAsbGVuZ3RoKHgpLTIpLDEpKSkKICBkZltzdGF0dXMudmFyXSA8LSBkZltzdGF0dXMudmFyXSAqIGtlZXAuc3RhdHVzCiAgZGYKfQoKCiM9PT09PT4gQ3JlYXRlIHRoZSBjb3VudGluZyBwcm9jZXNzIGRhdGEgZnJhbWUgPD09PT09IwpidXJuLmNwIDwtIGRmLmNwKGJ1cm4sJ1QxJywnRDEnKQpidXJuLmNwIDwtIHdpdGhpbihidXJuLmNwLHsgVDFaMSA8LSBsb2coc3RvcCkqWjE7IH0pIAoKIz09PT09PiBBcHBseSB0aGUgQ294IFByb3BvcnRpb25hbCBIYXphcmRzIG1vZGVsIDw9PT09PSMKY294cGgoU3VydihzdGFydCxzdG9wLEQxKSB+IFoxK1oyK1ozK1QxWjEsZGF0YT1idXJuLmNwKQoKCmBgYAoKCi0tLQoKIyBzdXJ2c3VwCgotIFBsb3R0aW5nIHN1cnZpdmFsIGN1cnZlcyB3aXRoIHRoZSBzdXJ2c3VwIHBhY2thZ2UgIAoKaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3N1cnZzdXAvdmlnbmV0dGVzL3N1cnZzdXBfaW50cm8uaHRtbAoKCmh0dHA6Ly9naXRodWIuY29tL2RsaW5kaG9sbS9zdXJ2c3VwLwoKCmBgYHtyfQojIGluc3RhbGwucGFja2FnZXMoInN1cnZzdXAiKQpgYGAKCgpgYGB7cn0KbGlicmFyeShzdXJ2c3VwKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3Vydml2YWwpCmxpYnJhcnkoZHBseXIpCmBgYAoKCmBgYHtyfQpsdW5nCmBgYAoKCgpgYGB7cn0KZml0IDwtIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IGx1bmcpCnBsb3Rfc3VydmZpdChmaXQpCmBgYAoKCmBgYHtyfQpsdW5nICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpCmBgYAoKCmBgYHtyfQpsdW5nICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gMSwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChjdW1pbmMgPSBGQUxTRSkKYGBgCgoKCmBgYHtyfQpsdW5nICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc2V4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KGN1bWluYyA9IEZBTFNFKQpgYGAKCgpgYGB7cn0KbHVuZyAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChjdW1pbmMgPSBGQUxTRSwgY2kgPSBUUlVFKQpgYGAKCgpgYGB7cn0KbHVuZyAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChjdW1pbmMgPSBGQUxTRSwgY2kgPSBUUlVFKSArICMgPC0tLSBOT1RFIQogIGxhYnMoeCA9ICJUaW1lIChkYXlzKSIsIHkgPSAiU3Vydml2YWwgKCUpIikKYGBgCgoKYGBge3J9Cmx1bmcgJT4lCiAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBzZXgsIGRhdGEgPSAuKSAlPiUKICBwbG90X3N1cnZmaXQoY3VtaW5jID0gRkFMU0UpICU+JQogIG5hcigpCmBgYAoKCgpgYGB7cn0KbHVuZyAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChjdW1pbmMgPSBGQUxTRSkgJT4lCiAgbmFyKHNpemUgPSAzKQpgYGAKCgoKYGBge3J9CmNvbG9uCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHJ4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrb3JhbmdlIiwgInN0ZWVsYmx1ZSIsICJkYXJrcmVkIikpCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpICU+JQogIG5hcigpICU+JQogIHNraXNsb3BlcygpCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpICU+JQogIG5hcigpICU+JQogIHNraXNsb3BlcyhyZXZlcnNlID0gVFJVRSkKYGBgCgoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpICU+JQogIG5hcigpICU+JQogIGNhdDQoKQpgYGAKCgoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpICU+JQogIG5hcigpICU+JQogIGhjbF9yYWluYm93KCkKYGBgCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gZXh0ZW50LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKCkgJT4lCiAgaGNsX3JhaW5ib3cocmV2ZXJzZSA9IFRSVUUpCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChsd2QgPSAyKQpgYGAKCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gZXh0ZW50LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KGx3ZCA9IDAuNSkKYGBgCgoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdChsZWdlbmQudGl0bGUgPSAiRXh0ZW50IG9mIGRpc2Vhc2UiKQpgYGAKCgoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCh5bGltID0gYygwLCAxMDApKSAlPiUKICBuYXIoKQpgYGAKCgpgYGB7cn0KY29sb24gJT4lCiAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBleHRlbnQsIGRhdGEgPSAuKSAlPiUKICBwbG90X3N1cnZmaXQoeG1heCA9IDIwMDApICU+JQogIG5hcigpCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCh4bWF4ID0gMjAwMCwgeGJyZWFrcyA9IGMoMCwgMTAwMCwgMjAwMCkpICU+JQogIG5hcigpCmBgYAoKCgpgYGB7cn0KY29sb24gJT4lCiAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBzZXgsIGRhdGEgPSAuKSAlPiUKICBwbG90X3N1cnZmaXQoKSAlPiUKICBuYXIoKQpgYGAKCgpgYGB7cn0KY29sb24gJT4lCiAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBzZXgsIGRhdGEgPSAuKSAlPiUKICBwbG90X3N1cnZmaXQoKSAlPiUKICBuYXIoZmxpcCA9IFRSVUUpCmBgYAoKCgpgYGB7cn0KY29sb24gJT4lCiAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBzZXgsIGRhdGEgPSAuKSAlPiUKICBwbG90X3N1cnZmaXQoKSAlPiUKICBuYXIoc2l6ZSA9IDUsIGZsaXAgPSBUUlVFKQpgYGAKCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc2V4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKHNpemUgPSAyLCBmbGlwID0gVFJVRSkKYGBgCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc2V4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKHlfb2Zmc2V0ID0gMC4xLCBmbGlwID0gVFJVRSkKYGBgCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc2V4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKHlfb2Zmc2V0ID0gMC4wMywgZmxpcCA9IFRSVUUpCmBgYAoKCmBgYHtyfQpjb2xvbiAlPiUKICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCwgZGF0YSA9IC4pICU+JQogIHBsb3Rfc3VydmZpdCgpICU+JQogIG5hcihzZXBhcmF0b3IgPSBGQUxTRSkKYGBgCgoKYGBge3J9CmNvbG9uICU+JQogIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc2V4LCBkYXRhID0gLikgJT4lCiAgcGxvdF9zdXJ2Zml0KCkgJT4lCiAgbmFyKHNlcF9jb2xvciA9ICJncmV5OTAiLCBzZXBfbHdkID0gMS41KQpgYGAKCgoKaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1ncmlkRXh0cmEKCgpgYGB7cn0KbGlicmFyeShncmlkRXh0cmEpCmBgYAogIAoKYGBge3J9CnAgPC0gbGlzdCgKICBwMSA9IGNvbG9uICU+JQogICAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiBzZXgsIGRhdGEgPSAuKSAlPiUKICAgIHBsb3Rfc3VydmZpdCh5bGltID0gYygwLCAxMDApKSAlPiUKICAgIG5hcigpICsKICAgIGxhYnModGFnID0gIkEiKSwKCiAgcDIgPSBjb2xvbiAlPiUKICAgIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gbm9kZTQsIGRhdGEgPSAuKSAlPiUKICAgIHBsb3Rfc3VydmZpdCh5bGltID0gYygwLCAxMDApKSAlPiUKICAgIG5hcigpICsKICAgIGxhYnModGFnID0gIkIiKQopCgpncmlkLmFycmFuZ2UoZ3JvYnMgPSBwLCBuY29sID0gMikKYGBgCgoKYGBge3J9CiMgU3RvcmUgcGxvdHMgaW4gYSBsaXN0CnAgPC0gbGlzdCgKICBwMSA9IGNvbG9uICU+JQogICAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiAxLCBkYXRhID0gLikgJT4lCiAgICBwbG90X3N1cnZmaXQoeWxpbSA9IGMoMCwgMTAwKSkgKwogICAgbGFicyh0YWcgPSAiQSIpLAoKICBwMiA9IGNvbG9uICU+JQogICAgc3VydmZpdChTdXJ2KHRpbWUsIHN0YXR1cykgfiByeCwgZGF0YSA9IC4pICU+JQogICAgcGxvdF9zdXJ2Zml0KHlsaW0gPSBjKDAsIDEwMCkpICU+JQogICAgbmFyKDIsIHNlcGFyYXRvciA9IEZBTFNFKSArCiAgICBsYWJzKHRhZyA9ICJCIiksCgogIHAzID0gY29sb24gJT4lCiAgICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IGV4dGVudCwgZGF0YSA9IC4pICU+JQogICAgcGxvdF9zdXJ2Zml0KHlsaW0gPSBjKDAsIDEwMCkpICU+JQogICAgbmFyKDIsIHNlcGFyYXRvciA9IEZBTFNFKSArCiAgICBsYWJzKHRhZyA9ICJDIiksCgogIHA0ID0gY29sb24gJT4lCiAgICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IHNleCwgZGF0YSA9IC4pICU+JQogICAgcGxvdF9zdXJ2Zml0KHlsaW0gPSBjKDAsIDEwMCkpICU+JQogICAgbmFyKDIsIHNlcGFyYXRvciA9IEZBTFNFKSArCiAgICBsYWJzKHRhZyA9ICJEIiksCgogIHA1ID0gY29sb24gJT4lCiAgICBzdXJ2Zml0KFN1cnYodGltZSwgc3RhdHVzKSB+IG5vZGU0LCBkYXRhID0gLikgJT4lCiAgICBwbG90X3N1cnZmaXQoeWxpbSA9IGMoMCwgMTAwKSkgJT4lCiAgICBuYXIoMiwgc2VwYXJhdG9yID0gRkFMU0UpICsKICAgIGxhYnModGFnID0gIkUiKSwKCiAgcDYgPSBjb2xvbiAlPiUKICAgIHN1cnZmaXQoU3Vydih0aW1lLCBzdGF0dXMpIH4gc3VyZywgZGF0YSA9IC4pICU+JQogICAgcGxvdF9zdXJ2Zml0KHlsaW0gPSBjKDAsIDEwMCkpICU+JQogICAgbmFyKDIsIHNlcGFyYXRvciA9IEZBTFNFKSArCiAgICBsYWJzKHRhZyA9ICJGIikKCikKCiNEZWZpbmUgbGF5b3V0IG1hdHJpeApsYXkgPC0gcmJpbmQoYygxLDEsMiksCiAgICAgICAgICAgICBjKDEsMSwzKSwKICAgICAgICAgICAgIGMoNCw1LDYpKQoKI1Bsb3QgaXQgYWxsIQpncmlkLmFycmFuZ2UoZ3JvYnMgPSBwLCBsYXlvdXRfbWF0cml4ID0gbGF5KQpgYGAKCgpgYGB7cn0KcFtbInAzIl1dCmBgYAoKCgojIHN1cnZpdmFsQW5hbHlzaXMKCgojIyBVbml2YXJpYXRlIFN1cnZpdmFsIEFuYWx5c2lzCgoKaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3N1cnZpdmFsQW5hbHlzaXMvdmlnbmV0dGVzL3VuaXZhcmlhdGUuaHRtbAoKCgoKCgoKCgoKCgoKCgoKCgoKCgo=